#ifndef NETWORKSERVICES_CLIENT_H
#define NETWORKSERVICES_CLIENT_H

#include <iostream>
#include <sys/select.h>
#include "HSocket.h"
#include "ThreadPool.h"

class Client {
public:
    Client(const std::string &ip, const uint16_t port)
    {
        servSock.fd = CreateSocket();
        servSock.ip = ip;
        servSock.port = port;
    }

    ~Client()
    {
        SAFE_CLOSESOCKET(servSock.fd);
    }

    std::string Recv() const
    {
        std::string data;
        int len;
        recv(fd, &len, 4, 0);            // 先读取4字节的报文头部。
        data.resize(len);
        recv(fd, data.data(), len, 0);   // 读取报文内容。
        return data;
    }

    void Send(const std::string &message)
    {
        std::string data;
        auto size = (int32_t) message.size();
        data.resize(size + 4);
        memcpy(data.data(), &size, sizeof(size));
        memcpy(data.data() + sizeof(size), message.data(), size);

        ssize_t ret = ::send(servSock.fd, data.data(), data.size(), 0);
        if (ret != -1) {
            syslog(LOG_INFO, "Send message: %s", data.data());
        } else {
            connected = false;
            while (!connected) {
                struct timeval tv{};
                tv.tv_sec = 0;
                tv.tv_usec = 1000;
                select(0, nullptr, nullptr, nullptr, &tv);
                Connect();
            }
            ::send(servSock.fd, data.data(), data.size(), 0);
            syslog(LOG_INFO, "Send message: %s", data.data());
        }
    }


    bool Connect()
    {
        if (!::Connect(servSock.fd, servSock.ip, servSock.port)) {
            syslog(LOG_ERR, "Connect failed!, errno: %d", errno);
            struct timeval tv{};
            tv.tv_sec = 3;
            tv.tv_usec = 0;
            select(0, nullptr, nullptr, nullptr, &tv);
        }

        connected = true;
        return true;
    }

public:
    int fd = -1;
    Socket servSock;
    std::atomic<bool> connected = true;
    ThreadPool threadPool;
};


#endif //NETWORKSERVICES_CLIENT_H
